//! Function signature utilities for NRC AST.

use serde::{Deserialize, Serialize};

use super::{FunctionDecl, Type};

/// Canonical representation of a function signature used for overload resolution.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FunctionSignature {
    /// Function name (without mangling).
    pub name: String,
    /// Parameter types in declaration order.
    pub parameter_types: Vec<Type>,
    /// Whether the function accepts a variadic tail (not yet exposed in syntax).
    pub is_variadic: bool,
}

impl FunctionSignature {
    /// Build a new signature.
    pub fn new(name: impl Into<String>, parameter_types: Vec<Type>, is_variadic: bool) -> Self {
        Self {
            name: name.into(),
            parameter_types,
            is_variadic,
        }
    }

    /// Create a signature directly from a function declaration.
    pub fn from_decl(func: &FunctionDecl) -> Self {
        Self {
            name: func.name.clone(),
            parameter_types: func
                .parameters
                .iter()
                .map(|p| p.param_type.clone())
                .collect(),
            is_variadic: false,
        }
    }

    /// Parameter count (excluding variadic expansion).
    pub fn arity(&self) -> usize {
        self.parameter_types.len()
    }
}

/// Resolved function target information (filled after overload resolution).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResolvedFunction {
    /// Selected overload signature.
    pub signature: FunctionSignature,
    /// Mangled name used for backend emission.
    pub mangled_name: String,
}
